﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using gdv;

namespace gdv
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class SchmittManuelOrbit : Microsoft.Xna.Framework.DrawableGameComponent
    {
        //cam + enum wohl besser als eigener GameComponent; im Falle des Hinzufügens weiterer Components!
        //Frage: Wie ermöglicht man den GameComponents Zugriff untereinander?
        private enum GameState
        {
            startScreen,
            inGame
        }
        private GameState gameState;
        private Matrix world, view, projection;
        private float yRotSun, yRotEarth, yRotEarthAxis, yRotMoon;
        private Model sphereModel, cubeModel;
        private float screenWidth, screenHeight;
        private float camFieldOfView = MathHelper.PiOver4;
        private Vector3 camPosition, camLookAt, camUp;
        private float sunRotCount, earthRotCount, earthRotAxisCount, moonRotCount;


        public SchmittManuelOrbit(Game game)
            : base(game)
        {
            // TODO: Construct any child components here

            //gameState = new GameState();
            gameState = GameState.inGame;
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here

            camPosition = new Vector3(0.0f, 25.0f, 0.000000000000000000001f);//wieso kann ich nichts direkt von oben sehen?
              camLookAt = new Vector3(0.0f, 0.0f, 0.0f);
                  camUp = new Vector3(0.0f, 1.0f, 0.0f);

             screenWidth = 1280.0f;
            screenHeight = 720.0f;

                 world = Matrix.Identity;
            projection = Matrix.CreatePerspectiveFieldOfView(camFieldOfView, screenWidth / screenHeight, 1.0f, 1000.0f);

            yRotSun = yRotEarth = yRotEarthAxis = yRotMoon = 0.0f;

             sunRotCount = earthRotCount = earthRotAxisCount = 0.0125f;
            moonRotCount = 0.00625f;

            base.Initialize();
        }

        protected override void LoadContent()
        {
            sphereModel = Game.Content.Load<Model>("Sphere");
              cubeModel = Game.Content.Load<Model>("Cube");//Zum besseren Erkennen von Rotationen um eigene Achse

            base.LoadContent();
        }

        protected override void UnloadContent()
        {
            base.UnloadContent();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here
            KeyboardState kb = Keyboard.GetState();
            if (kb.IsKeyDown(Keys.Escape))
                Game.Exit();
            if (kb.IsKeyDown(Keys.Right))
                SwitchOrbitDirectionClockwise();
            if (kb.IsKeyDown(Keys.Left))
                SwitchOrbitDirectionCounterclockwise();

            view = Matrix.CreateLookAt(camPosition, camLookAt, camUp);

            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            if (gameState.Equals(GameState.inGame))
            {
                  DrawSun();
                DrawEarth();
                 DrawMoon();
            }
            if (gameState.Equals(GameState.startScreen))
            {
            }

            base.Draw(gameTime);
        }

        private void DrawSun()
        {
            Matrix transformation = Matrix.CreateScale(new Vector3(2.5f, 2.5f, 2.5f)) *
                                       Matrix.CreateRotationY(yRotSun += sunRotCount);

            Vector3 gelb = new Vector3(1.0f, 1.0f, 0.0f);

            foreach (ModelMesh mesh in sphereModel.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    //effect.EnableDefaultLighting();

                    effect.AmbientLightColor = gelb;
                         //effect.DiffuseColor = gelb;

                         effect.World = world * transformation;
                          effect.View = view;
                    effect.Projection = projection;
                }
                mesh.Draw();
            }
        }

        private void DrawEarth()
        {
            Matrix transformation = Matrix.CreateRotationY(yRotEarthAxis += earthRotAxisCount) *
                                       Matrix.CreateTranslation(new Vector3(6.5f, 0.0f, 0.0f)) *
                                                          Matrix.CreateScale(1.0f, 1.0f, 1.0f) *
                                            Matrix.CreateRotationY(yRotEarth += earthRotCount);

            Vector3 blau = new Vector3(0.0f, 0.0f, 1.0f);

            foreach (ModelMesh mesh in sphereModel.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    //effect.EnableDefaultLighting();

                    effect.AmbientLightColor = blau;
                         //effect.DiffuseColor = blau;

                         effect.World = world * transformation;
                          effect.View = view;
                    effect.Projection = projection;
                }
                mesh.Draw();
            }
        }

        private void DrawMoon()//keine Drehung um eigene Achse
        {
            Matrix transformation = Matrix.CreateTranslation(new Vector3(-7.5f, 0.0f, 0.0f)) *
                                            Matrix.CreateRotationY(yRotMoon += moonRotCount) *
                                        Matrix.CreateScale(new Vector3(0.25f, 0.25f, 0.25f)) *
                                     Matrix.CreateTranslation(new Vector3(6.5f, 0.0f, 0.0f)) *
                                                           Matrix.CreateRotationY(yRotEarth);

            foreach (ModelMesh mesh in sphereModel.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();

                         effect.World = world * transformation;
                          effect.View = view;
                    effect.Projection = projection;
                }
                mesh.Draw();
            }
        }

        public void SwitchOrbitDirection()
        {
                  sunRotCount = -sunRotCount;
                earthRotCount = -earthRotCount;
            earthRotAxisCount = -earthRotAxisCount;
                 moonRotCount = -moonRotCount;
        }

        public void SwitchOrbitDirectionClockwise()
        {
            if (sunRotCount > 0.0f)
            {
                      sunRotCount = -sunRotCount;
                    earthRotCount = -earthRotCount;
                earthRotAxisCount = -earthRotAxisCount;
                     moonRotCount = -moonRotCount;
            }
        }

        public void SwitchOrbitDirectionCounterclockwise()
        {
            if (sunRotCount < 0.0f)
            {
                      sunRotCount = -sunRotCount;
                    earthRotCount = -earthRotCount;
                earthRotAxisCount = -earthRotAxisCount;
                     moonRotCount = -moonRotCount;
            }
        }

        public void SetGameState(String state)
        {
            if (state.Equals("startScreen"))
                gameState = GameState.startScreen;
            if (state.Equals("inGame"))
                gameState = GameState.inGame;
            else Console.WriteLine("void Orbit.SetGameState(String state): Bitte wählen Sie zwischen folgenden Parametern aus: \"startScreen\", \"inGame\".");
        }
    }
}
